home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ohlfind.zip
/
PARSER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-03
|
24KB
|
993 lines
/* The Parsers and associated routines for Find.
Copyright (C) 1987, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#ifndef USG
#include <strings.h>
#else
#include <string.h>
#define index strchr
#define rindex strrchr
#endif
#include "modechange.h"
#include "defs.h"
#ifndef S_IFLNK
#define lstat stat
#endif
/* no parse_and */
boolean parse_atime ();
boolean parse_close ();
boolean parse_ctime ();
boolean parse_depth ();
boolean parse_exec ();
boolean parse_fstype ();
boolean parse_fulldays ();
boolean parse_group ();
boolean parse_inum ();
boolean parse_links ();
boolean parse_ls ();
boolean parse_mtime ();
boolean parse_name ();
boolean parse_negate ();
boolean parse_newer ();
boolean parse_nogroup ();
boolean parse_nouser ();
boolean parse_ok ();
boolean parse_open ();
boolean parse_or ();
boolean parse_perm ();
boolean parse_permmask ();
boolean parse_print ();
boolean parse_prune ();
boolean parse_regex ();
boolean parse_size ();
boolean parse_type ();
boolean parse_user ();
boolean parse_version ();
boolean parse_xdev ();
boolean pred_and ();
boolean pred_atime ();
boolean pred_close ();
boolean pred_ctime ();
/* no pred_depth */
boolean pred_exec ();
boolean pred_fstype ();
/* no pred_fulldays */
boolean pred_group ();
boolean pred_inum ();
boolean pred_links ();
boolean pred_ls ();
boolean pred_mtime ();
boolean pred_name ();
boolean pred_negate ();
boolean pred_newer ();
boolean pred_nogroup ();
boolean pred_nouser ();
boolean pred_ok ();
boolean pred_open ();
boolean pred_or ();
boolean pred_perm ();
boolean pred_permmask ();
boolean pred_print ();
boolean pred_prune ();
boolean pred_regex ();
boolean pred_size ();
boolean pred_type ();
boolean pred_user ();
/* no pred_version */
/* no pred_xdev */
long atol ();
struct group *getgrnam ();
struct passwd *getpwnam ();
struct tm *localtime ();
void endgrent ();
void endpwent ();
boolean get_num ();
boolean insert_exec_ok ();
boolean insert_num ();
boolean insert_time ();
char *find_pred_name ();
void read_mtab ();
#ifdef DEBUG
char *find_pred_name ();
#endif /* DEBUG */
struct parser_table_t
{
char *parser_name;
PFB parser_func;
};
struct parser_table_t parse_table[] =
{
{"!", parse_negate},
{"(", parse_open},
{")", parse_close},
#ifdef UNIMPLEMENTED_UNIX
{"a", parse_and}, /* do-nothing */
#endif
{"atime", parse_atime},
#ifdef UNIMPLEMENTED_UNIX
{"cpio", parse_cpio},
#endif
{"ctime", parse_ctime},
{"depth", parse_depth},
{"exec", parse_exec},
{"fulldays", parse_fulldays}, /* nonstandard */
{"fstype", parse_fstype},
{"group", parse_group},
{"inum", parse_inum}, /* nonstandard, Unix */
{"links", parse_links},
{"ls", parse_ls}, /* nonstandard, Unix */
{"mtime", parse_mtime},
{"name", parse_name},
#ifdef UNIMPLEMENTED_UNIX
{"ncpio", parse_ncpio},
#endif
{"newer", parse_newer},
{"nogroup", parse_nogroup},
{"nouser", parse_nouser},
{"o", parse_or},
{"or", parse_or}, /* nonstandard */
{"ok", parse_ok},
{"perm", parse_perm},
{"permmask", parse_permmask}, /* nonstandard */
{"print", parse_print},
{"prune", parse_prune},
{"regex", parse_regex}, /* nonstandard */
{"size", parse_size},
{"type", parse_type},
{"user", parse_user},
{"version", parse_version},
{"xdev", parse_xdev},
{0, 0}
};
/* Return a pointer to the parser function to invoke for predicate
SEARCH_NAME.
Return NULL if SEARCH_NAME is not a valid predicate name. */
PFB
find_parser (search_name)
char *search_name;
{
int i;
if (*search_name == '-')
search_name++;
for (i = 0; parse_table[i].parser_name != 0; i++)
if (strcmp (parse_table[i].parser_name, search_name) == 0)
return (parse_table[i].parser_func);
return (NULL);
}
/* The parsers are responsible to continue scanning ARGV for
their arguments. Each parser knows what is and isn't
allowed for itself.
ARGV is the argument array.
*ARG_PTR is the index to start at in ARGV,
updated to point beyond the last element consumed.
The predicate structure is updated with the new information. */
boolean
parse_atime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_atime));
}
boolean
parse_close (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred ();
our_pred->pred_func = pred_close;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_close);
#endif /* DEBUG */
our_pred->p_type = CLOSE_PAREN;
our_pred->p_prec = NO_PREC;
return (true);
}
boolean
parse_ctime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_ctime));
}
boolean
parse_depth (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
do_dir_first = false;
return (true);
}
boolean
parse_exec (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_exec_ok (pred_exec, argv, arg_ptr));
}
boolean
parse_fulldays (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct tm *local;
if (full_days == false)
{
cur_day_start += DAYSECS;
local = localtime (&cur_day_start);
cur_day_start -= local->tm_sec + local->tm_min * 60
+ local->tm_hour * 3600;
full_days = true;
}
return (true);
}
boolean
parse_fstype (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_fstype);
our_pred->args.str = argv[*arg_ptr];
(*arg_ptr)++;
read_mtab ();
return (true);
}
boolean
parse_group (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct group *cur_gr;
struct pred_struct *our_pred;
int gid, gid_len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
cur_gr = getgrnam (argv[*arg_ptr]);
endgrent ();
if (cur_gr != NULL)
gid = cur_gr->gr_gid;
else
{
gid_len = strspn (argv[*arg_ptr], "0123456789");
if ((gid_len == 0) || (argv[*arg_ptr][gid_len] != '\0'))
return (false);
gid = atoi (argv[*arg_ptr]);
}
our_pred = insert_victim (pred_group);
our_pred->args.gid = (short) gid;
(*arg_ptr)++;
return (true);
}
boolean
parse_inum (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_num (argv, arg_ptr, pred_inum));
}
boolean
parse_links (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_num (argv, arg_ptr, pred_links));
}
boolean
parse_ls (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_ls);
our_pred->side_effects = true;
return (true);
}
boolean
parse_mtime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_mtime));
}
boolean
parse_name (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_name);
our_pred->args.str = argv[*arg_ptr];
(*arg_ptr)++;
return (true);
}
boolean
parse_negate (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred_chk_op ();
our_pred->pred_func = pred_negate;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_negate);
#endif /* DEBUG */
our_pred->p_type = UNI_OP;
our_pred->p_prec = NEGATE_PREC;
return (true);
}
boolean
parse_newer (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
struct stat stat_newer;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (lstat (argv[*arg_ptr], &stat_newer))
error (1, errno, "%s", argv[*arg_ptr]);
our_pred = insert_victim (pred_newer);
our_pred->args.time = stat_newer.st_mtime;
(*arg_ptr)++;
return (true);
}
boolean
parse_nogroup (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_nogroup);
return (true);
}
boolean
parse_nouser (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_nouser);
return (true);
}
boolean
parse_ok (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
boolean insert_exec_ok ();
return (insert_exec_ok (pred_ok, argv, arg_ptr));
}
boolean
parse_open (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred_chk_op ();
our_pred->pred_func = pred_open;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_open);
#endif /* DEBUG */
our_pred->p_type = OPEN_PAREN;
our_pred->p_prec = NO_PREC;
return (true);
}
boolean
parse_or (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred ();
our_pred->pred_func = pred_or;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_or);
#endif /* DEBUG */
our_pred->p_type = BI_OP;
our_pred->p_prec = OR_PREC;
return (true);
}
boolean
parse_perm (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long perm_val;
int mode_start = 0;
struct mode_change *change;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (argv[*arg_ptr][0] == '-')
mode_start = 1;
change = mode_compile (argv[*arg_ptr] + mode_start, MODE_MASK_PLUS);
if (change == MODE_INVALID)
error (1, 0, "invalid mode `%s'", argv[*arg_ptr]);
else if (change == MODE_MEMORY_EXHAUSTED)
error (1, 0, "virtual memory exhausted");
perm_val = mode_adjust (0, change);
mode_free (change);
our_pred = insert_victim (pred_perm);
if (mode_start)
/* Set magic flag to compare suid, sgid, sticky bits as well;
also, true if at least the given bits are set. */
our_pred->args.perm = (perm_val & 07777) | 010000;
else
our_pred->args.perm = perm_val & 0777;
(*arg_ptr)++;
return (true);
}
boolean
parse_permmask (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long mask_val;
struct mode_change *change;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
change = mode_compile (argv[*arg_ptr], MODE_MASK_PLUS);
if (change == MODE_INVALID)
error (1, 0, "invalid mode mask `%s'", argv[*arg_ptr]);
else if (change == MODE_MEMORY_EXHAUSTED)
error (1, 0, "virtual memory exhausted");
mask_val = mode_adjust (0, change);
mode_free (change);
our_pred = insert_victim (pred_permmask);
our_pred->args.perm = mask_val;
(*arg_ptr)++;
return (true);
}
boolean
parse_print (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_print);
/* -print has the side effect of printing. This prevents us
from doing undesired multiple printing when the user has
already specified -print. */
our_pred->side_effects = true;
return (true);
}
boolean
parse_prune (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_prune);
return (true);
}
boolean
parse_regex (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
struct re_pattern_buffer *re;
char *error_message;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_regex);
re = (struct re_pattern_buffer *)
xmalloc (sizeof (struct re_pattern_buffer));
our_pred->args.regex = re;
re->allocated = 100;
re->buffer = xmalloc (re->allocated);
re->fastmap = NULL;
re->translate = NULL;
error_message = re_compile_pattern (argv[*arg_ptr], strlen (argv[*arg_ptr]),
re);
if (error_message)
error (1, 0, "%s", error_message);
(*arg_ptr)++;
return (true);
}
boolean
parse_size (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
unsigned long num;
short c_type;
boolean blk;
int len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
len = strlen (argv[*arg_ptr]);
if (len == 0)
error (1, 0, "invalid null argument to -size");
switch (argv[*arg_ptr][len - 1])
{
case 'c':
blk = false;
argv[*arg_ptr][len - 1] = '\0';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
blk = true;
break;
default:
error (1, 0, "invalid -size type `%c'", argv[*arg_ptr][len - 1]);
}
if (!get_num (argv[*arg_ptr], &num, &c_type))
return (false);
our_pred = insert_victim (pred_size);
our_pred->args.size.kind = c_type;
our_pred->args.size.block = blk;
our_pred->args.size.size = num;
(*arg_ptr)++;
return (true);
}
boolean
parse_type (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long type_cell;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL)
|| (strlen (argv[*arg_ptr]) != 1))
return (false);
switch (argv[*arg_ptr][0])
{
case 'b': /* block special */
type_cell = S_IFBLK;
break;
case 'c': /* character special */
type_cell = S_IFCHR;
break;
case 'd': /* directory */
type_cell = S_IFDIR;
break;
case 'f': /* regular file */
type_cell = S_IFREG;
break;
#ifdef S_IFLNK
case 'l': /* symbolic link */
type_cell = S_IFLNK;
break;
#endif
#ifdef S_IFIFO
case 'p': /* pipe */
type_cell = S_IFIFO;
break;
#endif
#ifdef S_IFSOCK
case 's': /* socket */
type_cell = S_IFSOCK;
break;
#endif
default: /* none of the above ... nuke em */
return (false);
}
our_pred = insert_victim (pred_type);
our_pred->args.type = type_cell;
(*arg_ptr)++; /* move on to next argument */
return (true);
}
boolean
parse_user (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct passwd *cur_pwd;
struct pred_struct *our_pred;
int uid, uid_len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
cur_pwd = getpwnam (argv[*arg_ptr]);
endpwent ();
if (cur_pwd != NULL)
uid = cur_pwd->pw_uid;
else
{
uid_len = strspn (argv[*arg_ptr], "0123456789");
if ((uid_len == 0) || (argv[*arg_ptr][uid_len] != '\0'))
return (false);
uid = atoi (argv[*arg_ptr]);
}
our_pred = insert_victim (pred_user);
our_pred->args.uid = (short) uid;
(*arg_ptr)++;
return (true);
}
boolean
parse_version (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
extern char *version_string;
fprintf (stderr, "%s", version_string);
return true;
}
boolean
parse_xdev (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
stay_on_filesystem = true;
return true;
}
boolean
insert_exec_ok (func, argv, arg_ptr)
boolean (*func) ();
char *argv[];
int *arg_ptr;
{
int start, end; /* Indexes in ARGV of start & end of cmd. */
int num_paths; /* Number of "{}" insertions to do. */
int path_pos; /* Index in array of "{}" insertions. */
int vec_pos; /* Index in array of arg words. */
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
start = *arg_ptr;
for (end = start, num_paths = 0;
(argv[end] != NULL)
&& ((argv[end][0] != ';') || (argv[end][1] != '\0'));
end++)
if (strcmp (argv[end], "{}") == 0)
num_paths++;
/* Fail if no command given or no semicolon found. */
if ((end == start) || (argv[end] == NULL))
{
*arg_ptr = end;
return (false);
}
our_pred = insert_victim (func);
our_pred->side_effects = true;
our_pred->args.exec_vec.path_loc =
(short *) xmalloc (sizeof (short) * (num_paths + 1));
our_pred->args.exec_vec.vec =
(char **) xmalloc (sizeof (char *) * (end - start + 1));
for (end = start, path_pos = vec_pos = 0;
(argv[end] != NULL)
&& ((argv[end][0] != ';') || (argv[end][1] != '\0'));
end++)
{
if (strcmp (argv[end], "{}") == 0)
our_pred->args.exec_vec.path_loc[path_pos++] = vec_pos;
our_pred->args.exec_vec.vec[vec_pos++] = argv[end];
}
our_pred->args.exec_vec.path_loc[path_pos] = -1;
our_pred->args.exec_vec.vec[vec_pos] = NULL;
if (argv[end] == NULL)
*arg_ptr = end;
else
*arg_ptr = end + 1;
return (true);
}
/* Get a number of days and comparison type.
STR is the ASCII representation.
Set *NUM_DAYS to the number of days, taken as being from
the current moment (or possibly midnight). Thus the sense of the
comparison type appears to be reversed.
Set *COMP_TYPE to the kind of comparison that is requested.
Return true if all okay, false if input error.
Used by -atime, -ctime and -mtime (parsers) to
get the appropriate information for a time predicate processor. */
boolean
get_num_days (str, num_days, comp_type)
char *str;
unsigned long *num_days;
enum comparison_type *comp_type;
{
int len_days; /* length of field */
if (str == NULL)
return (false);
switch (str[0])
{
case '+':
*comp_type = COMP_LT;
str++;
break;
case '-':
*comp_type = COMP_GT;
str++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*comp_type = COMP_EQ;
break;
default:
return (false);
}
/* We know the first char has been reasonable. Find the
number of days to play with. */
len_days = strspn (str, "0123456789");
if ((len_days == 0) || (str[len_days] != '\0'))
return (false);
*num_days = (unsigned long) atol (str);
return (true);
}
/* Insert a time predicate PRED.
ARGV is a pointer to the argument array.
ARG_PTR is a pointer to an index into the array, incremented if
all went well.
Return true if input is valid, false if not.
A new predicate node is assigned, along with an argument node
obtained with malloc.
Used by -atime, -ctime, and -mtime parsers. */
boolean
insert_time (argv, arg_ptr, pred)
char *argv[];
int *arg_ptr;
PFB pred;
{
struct pred_struct *our_pred;
unsigned long num_days;
enum comparison_type c_type;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (!get_num_days (argv[*arg_ptr], &num_days, &c_type))
return (false);
our_pred = insert_victim (pred);
our_pred->args.info.kind = c_type;
our_pred->args.info.l_val = cur_day_start - num_days * DAYSECS
+ ((c_type == COMP_GT) ? DAYSECS - 1 : 0);
(*arg_ptr)++;
#ifdef DEBUG
printf ("inserting %s\n", our_pred->p_name);
printf (" type: %s %s ",
(c_type == COMP_GT) ? "gt" :
((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
(c_type == COMP_GT) ? " >" :
((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? ">=" : " ?")));
printf ("%ld %s", our_pred->args.info.l_val,
ctime (&our_pred->args.info.l_val));
if (c_type == COMP_EQ)
{
our_pred->args.info.l_val += DAYSECS;
printf (" < %ld %s", our_pred->args.info.l_val,
ctime (&our_pred->args.info.l_val));
our_pred->args.info.l_val -= DAYSECS;
}
#endif /* DEBUG */
return (true);
}
/* Get a number with comparision information.
The sense of the comparision information is 'normal'; that is,
'+' looks for inums or links > than the number and '-' less than.
STR is the ASCII representation of the number.
Set *NUM to the number.
Set *COMP_TYPE to the kind of comparison that is requested.
Return true if all okay, false if input error.
Used by the -inum and -links predicate parsers. */
boolean
get_num (str, num, comp_type)
char *str;
unsigned long *num;
short *comp_type;
{
int len_num; /* length of field */
if (str == NULL)
return (false);
switch (str[0])
{
case '+':
*comp_type = COMP_GT;
str++;
break;
case '-':
*comp_type = COMP_LT;
str++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*comp_type = COMP_EQ;
break;
default:
return (false);
}
/* We know the first char has been reasonable. Find the number of
days to play with. */
len_num = strspn (str, "0123456789");
if ((len_num == 0) || (str[len_num] != '\0'))
return (false);
*num = (unsigned long) atol (str);
return (true);
}
/* Insert a number predicate.
ARGV is a pointer to the argument array.
*ARG_PTR is an index into ARGV, incremented if all went well.
*PRED is the predicate processor to insert.
Return true if input is valid, false if error.
A new predicate node is assigned, along with an argument node
obtained with malloc.
Used by -inum and -links parsers. */
boolean
insert_num (argv, arg_ptr, pred)
char *argv[];
int *arg_ptr;
PFB pred;
{
struct pred_struct *our_pred;
unsigned long num;
short c_type;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (!get_num (argv[*arg_ptr], &num, &c_type))
return (false);
our_pred = insert_victim (pred);
our_pred->args.info.kind = c_type;
our_pred->args.info.l_val = num;
(*arg_ptr)++;
#ifdef DEBUG
printf ("inserting %s\n", our_pred->p_name);
printf (" type: %s %s ",
(c_type == COMP_GT) ? "gt" :
((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
(c_type == COMP_GT) ? " >" :
((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
printf ("%ld\n", our_pred->args.info.l_val);
#endif /* DEBUG */
return (true);
}
#ifdef STRSPN_MISSING
int
strspn (str, class)
char *str, *class;
{
register char *cl = class;
register char *st = str;
while (index (class, *st))
++st;
return st - str;
}
#endif